using System;
using System.Collections.Generic;
using System.IO;

namespace PeDALS.Tools.AZ.PSTArchive.PSTData
{
    public class PSTHeader
    {
        private int mdwMagic;
        private int mdwCRCPartial;
        private short mwMagicClient;
        private short mwVer;
        private short mwVerClient;
        private byte mbPlatformCreate;
        private byte mbPlatformAccess;
        private int mdwReserved1OpenDBID;
        private int mdwReserved2OpenClaimID;
        private long mbidUnused;
        private UInt64 m64BIDrawNext;
        private UInt64 m64BIDrawNextPage;
        private int mdwUnique;
        private List<UInt64> m64NIDrawrgnid = new List<UInt64>();
        private long mqwUnusedAlign;
        private int mdwRootReservedcOrphans;
        private long mlngFileEOF;
        private long mlngAllocationMapLastAddress;
        private long mlngAllocationMapFree;
        private long mlngPageMapFree;
        private UInt64 m64BIDrawNodeBT;
        private long mlngNodeBTAddress;
        private UInt64 m64BIDrawBlockBT;
        private long mlngBlockBTAddress;
        private byte mfAllocationMapValid;
        private byte mbRootReservedbARVec;
        private short mwRootReservedcARVec;
        private int mdwAlign;
        private byte[] mrgbFreeMap = new byte[128];
        private byte[] mrgbFreePageMap = new byte[128];
        private byte mbSentinel;
        private byte mbCryptMethod;
        private short mrgbReserved;
        private int mdwCRCFull;
        private byte[] mrgbReserved2 = new byte[3];
        private byte mbReserved;
        private byte[] mrgbReserved3 = new byte[32];

        public PSTHeader(BinaryReader brReader)
        {
            mdwMagic = brReader.ReadInt32();
            mdwCRCPartial = brReader.ReadInt32();
            mwMagicClient = brReader.ReadInt16();
            mwVer = brReader.ReadInt16();
            mwVerClient = brReader.ReadInt16();
            mbPlatformCreate = brReader.ReadByte();
            mbPlatformAccess = brReader.ReadByte();
            mdwReserved1OpenDBID = brReader.ReadInt32();
            mdwReserved2OpenClaimID = brReader.ReadInt32();
            if (Unicode) mbidUnused = brReader.ReadInt64();
            if (!Unicode) m64BIDrawNext = Convert.ToUInt64(brReader.ReadUInt32());
            m64BIDrawNextPage = Unicode ? brReader.ReadUInt64() : Convert.ToUInt64(brReader.ReadUInt32());
            mdwUnique = brReader.ReadInt32();
            for (int intI = 0; intI < 32; intI++)
            {
                m64NIDrawrgnid.Add(Convert.ToUInt64(brReader.ReadInt32()));
            }
            if (Unicode) mqwUnusedAlign = brReader.ReadInt64();
            mdwRootReservedcOrphans = brReader.ReadInt32();
            mlngFileEOF = Unicode ? brReader.ReadInt64() : Convert.ToInt64(brReader.ReadInt32());
            mlngAllocationMapLastAddress = Unicode ? brReader.ReadInt64() : Convert.ToInt64(brReader.ReadInt32());
            mlngAllocationMapFree = Unicode ? brReader.ReadInt64() : Convert.ToInt64(brReader.ReadInt32());
            mlngPageMapFree = Unicode ? brReader.ReadInt64() : Convert.ToInt64(brReader.ReadInt32());
            m64BIDrawNodeBT = Unicode ? brReader.ReadUInt64() : Convert.ToUInt64(brReader.ReadUInt32());
            mlngNodeBTAddress = Unicode ? brReader.ReadInt64() : Convert.ToInt64(brReader.ReadInt32());
            m64BIDrawBlockBT = Unicode ? brReader.ReadUInt64() : Convert.ToUInt64(brReader.ReadUInt32());
            mlngBlockBTAddress = Unicode ? brReader.ReadInt64() : Convert.ToInt64(brReader.ReadInt32());
            mfAllocationMapValid = brReader.ReadByte();
            mbRootReservedbARVec = brReader.ReadByte();
            mwRootReservedcARVec = brReader.ReadInt16();
            if (Unicode) mdwAlign = brReader.ReadInt32();
            mrgbFreeMap = brReader.ReadBytes(128);
            mrgbFreePageMap = brReader.ReadBytes(128);
            mbSentinel = brReader.ReadByte();
            mbCryptMethod = brReader.ReadByte();
            mrgbReserved = brReader.ReadInt16();
            if (Unicode) m64BIDrawNext = brReader.ReadUInt64();
            if (!Unicode) mqwUnusedAlign = brReader.ReadInt64();
            mdwCRCFull = brReader.ReadInt32();
            mrgbReserved2 = brReader.ReadBytes(3);
            mbReserved = brReader.ReadByte();
            mrgbReserved3 = brReader.ReadBytes(32);
        }

        public int dwMagic
        {
            get { return mdwMagic; }
        }

        public int dwCRCPartial
        {
            get { return mdwCRCPartial; }
        }

        public short wMagicClient
        {
            get { return mwMagicClient; }
        }

        public short wVer
        {
            get { return mwVer; }
        }

        public short wVerClient 
        {
            get { return mwVerClient; }
        }

        public byte bPlatformCreate 
        {
            get { return mbPlatformCreate; }
        }

        public byte bPlatformAccess 
        {
            get { return mbPlatformAccess; }
        }

        public int dwReserved1OpenDBID
        {
            get { return mdwReserved1OpenDBID; }
        }

        public int dwReserved2OpenClaimID
        {
            get { return mdwReserved2OpenClaimID; }
        }

        public long bidUnused 
        {
            get { return mbidUnused; }
        }

        public UInt64 BIDrawNext 
        {
            get { return m64BIDrawNext; }
        }

        public UInt64 BIDrawNextPage 
        {
            get { return m64BIDrawNextPage; }
        }

        public int dwUnique
        {
            get { return mdwUnique; }
        }

        public List<UInt64> NIDrawrgnid 
        {
            get { return m64NIDrawrgnid; }
        }

        public long qwUnusedAlign 
        {
            get { return mqwUnusedAlign; }
        }

        public int dwRootReservedcOrphans
        {
            get { return mdwRootReservedcOrphans; }
        }

        public long lngFileEOF 
        {
            get { return mlngFileEOF; }
        }

        public long lngAllocationMapLastAddress
        {
            get { return mlngAllocationMapLastAddress; }
        }

        public long lngAllocationMapFree 
        {
            get { return mlngAllocationMapFree; }
        }

        public long lngPageMapFree 
        {
            get { return mlngPageMapFree; }
        }

        public UInt64 BIDrawNodeBT 
        {
            get { return m64BIDrawNodeBT; }
        }

        public long lngNodeBTAddress 
        {
            get { return mlngNodeBTAddress; }
        }

        public UInt64 BIDrawBlockBT 
        {
            get { return m64BIDrawBlockBT; }
        }

        public long lngBlockBTAddress 
        {
            get { return mlngBlockBTAddress; }
        }

        public byte fAllocationMapValid 
        {
            get { return mfAllocationMapValid; }
        }

        public byte bRootReservedbARVec 
        {
            get { return mbRootReservedbARVec; }
        }

        public short wRootReservedcARVec
        {
            get { return mwRootReservedcARVec; }
        }

        public int dwAlign
        {
            get { return mdwAlign; }
        }

        public byte[] rgbFreeMap 
        {
            get { return mrgbFreeMap; }
        }

        public byte[] rgbFreePageMap 
        {
            get { return mrgbFreePageMap; }
        }

        public byte bSentinel 
        {
            get { return mbSentinel; }
        }

        public byte bCryptMethod 
        {
            get { return mbCryptMethod; }
        }

        public short rgbReserved 
        {
            get { return mrgbReserved; }
        }

        public int dwCRCFull
        {
            get { return mdwCRCFull; }
        }

        public byte[] rgbReserved2 
        {
            get { return mrgbReserved2; }
        }

        public byte bReserved 
        {
            get { return mbReserved; }
        }

        public byte[] rgbReserved3 
        {
            get { return mrgbReserved3; }
        }

        public bool Unicode
        {
            get { return wVer == 23; }
        }
    }
}